package com.wushijia.java8.stream;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * Examples how to avoid null checks with Optional:
 *
 * http://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/
 *
 * @author Benjamin Winterberg
 */
public class Optional2 {

  static class Outer {

    Nested nested = new Nested();

    private Nested getNested() {
      return nested;
    }
  }

  static class Nested {

    Inner inner = new Inner();

    private Inner getInner() {
      return inner;
    }
  }

  static class Inner {

    String foo = "boo";

    public String getFoo() {
      return foo;
    }
  }

  public static void main(String[] args) {
    test1();
    test2();
    test3();
    test4();
  }

  private static <T> Optional<T> resolve(Supplier<T> resolver) {
    try {
      T result = resolver.get();
      return Optional.ofNullable(result);
    } catch (NullPointerException e) {
      return Optional.empty();
    }
  }

  private static void test4() {
    Inner inner = new Inner();
    Optional<Inner> optional = Optional.of(inner);
    System.out.println(optional.filter(inner2 -> inner2.getFoo() != null).get().getFoo());
  }

  private static void test3() {
    Outer outer = new Outer();
    resolve(() -> outer.getNested().getInner().getFoo())
        .ifPresent(System.out::println);
  }

  private static void test2() {
    Optional.of(new Outer())
        .map(Outer::getNested)
        .map(Nested::getInner)
        .map(Inner::getFoo)
        .ifPresent(System.out::println);
  }

  private static void test1() {
    Optional.of(new Outer())
        .flatMap(o -> Optional.ofNullable(o.nested))
        .flatMap(n -> Optional.ofNullable(n.inner))
        .flatMap(i -> Optional.ofNullable(i.foo))
        .ifPresent(System.out::println);
  }
}
